package com.dayuanit.dy15.atm.bean;

import com.dayuanit.dy15.atm.annotation.AutoWired;
import com.dayuanit.dy15.atm.annotation.Component;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 默认的对象工厂
 */
public class DefaultBeanFactory implements BeanFactory {
    //保存对象的 k=对象的名称  v=对象
    private static final Map<String, Object> objectMap = new HashMap<>();

    @Override
    public Object getBean(String beanName) {
        return objectMap.get(beanName);
    }

    @Override
    public void builder(String... packagePath) throws Exception {
        for (String path : packagePath) {
            //通过给定的包，创建该包下所有类的对象。

            //第一步，创建对象
            ioc(path);

            //第二步：为对象赋上初始值 解决对象之间依赖关系
            di();
        }
    }

    @Override
    public Map<String, Object> getObjects() {
        return objectMap;
    }

    //IOC 控制反转  controller对象 service对象都创建好了 但是木有解决对象和对象之间的依赖关系
    private void ioc(String packagePath) throws Exception {
        Enumeration<URL> resources = DefaultBeanFactory.class
                .getClassLoader().getResources(packagePath);

        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
            ///D:/dayuanit/15/atmweb-v2/target/atm-web-v2/WEB-INF/classes/com/dayuanit/dy15/atm/controller/
            System.out.println(url.getFile());

            //包的绝对路径
            File file = new File(url.getFile());

            //包下面的所有文件(字节码文件)
            File[] files = file.listFiles();
            for (File f : files) {
                System.out.println(">>>>>>fileName=" + f.getName());
                String fileName = f.getName();

                //包名+class文件名去掉.class后缀名 = 类的全名称
                String className = packagePath.replace("/",".") + "." + fileName.substring(0, fileName.length() - 6);
                System.out.println("className=" + className);

                Class clazz = Class.forName(className);
                //只有类上面有Component注解的类才能够添加
                Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();
                for (Annotation annotation : declaredAnnotations) {
                    if (annotation.annotationType() == Component.class) {
                        Component component = (Component) annotation;
                        objectMap.put(component.value(), clazz.newInstance());
                    }
                }
            }

        }

        for (Map.Entry<String, Object> entry : objectMap.entrySet()) {
            System.out.println("对象的名字>>>>>" + entry.getKey() + "=" + entry.getValue());
        }
    }

    //依赖注入  解决对象之间的依赖关系
    private void di() throws Exception {
        //遍历所有的对象 调用set方法为成员变量赋值
        for (Map.Entry<String, Object> entry : objectMap.entrySet()) {
            Object object = entry.getValue();
            Class clazz = object.getClass();

            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method method : declaredMethods) {
                Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
                for (Annotation annotation : declaredAnnotations) {
                    if (annotation.annotationType() == AutoWired.class) {
                        AutoWired autoWired = (AutoWired)annotation;
                        //入参对象的名字  @AutoWired("flowServiceImpl")
                        String objectName = autoWired.value();
                        //通过对象名字 找对入参对象
                        Object paramObject = objectMap.get(objectName);

                        //调用当前方法 也就set方法
                        method.invoke(object, paramObject);
                    }
                }
            }

        }
    }


}
